﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    public class HttpHelper
    {
        public static string GenerateFileMD5Identifier(string filePath)
        {
            using (var md5 = System.Security.Cryptography.MD5.Create())
            {
                using (var stream = System.IO.File.OpenRead(filePath))
                {
                    // 计算文件内容的哈希值
                    byte[] contentHash = md5.ComputeHash(stream);

                    // 获取文件属性的字符串表示
                    System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
                    string fileProperties = $"{fileInfo.Length}{fileInfo.LastWriteTimeUtc}{fileInfo.Attributes}";

                    // 计算文件属性的哈希值
                    byte[] propertiesHash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(fileProperties));

                    // 合并内容哈希和属性哈希
                    byte[] combinedHash = new byte[contentHash.Length + propertiesHash.Length];
                    Buffer.BlockCopy(contentHash, 0, combinedHash, 0, contentHash.Length);
                    Buffer.BlockCopy(propertiesHash, 0, combinedHash, contentHash.Length, propertiesHash.Length);

                    // 将哈希值转换为字符串表示
                    return BitConverter.ToString(md5.ComputeHash(combinedHash)).Replace("-", "").ToLower();
                }
            }
        }
        public static string GenerateFileSHA256Identifier(string filePath)
        {
            using (var sha256 = System.Security.Cryptography.SHA256.Create())
            {
                using (var stream = System.IO.File.OpenRead(filePath))
                {
                    // 计算文件内容的哈希值
                    byte[] contentHash = sha256.ComputeHash(stream);

                    // 获取文件属性的字符串表示
                    System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
                    string fileProperties = $"{fileInfo.Length}{fileInfo.LastWriteTimeUtc}{fileInfo.Attributes}";

                    // 计算文件属性的哈希值
                    byte[] propertiesHash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(fileProperties));

                    // 合并内容哈希和属性哈希
                    byte[] combinedHash = new byte[contentHash.Length + propertiesHash.Length];
                    Buffer.BlockCopy(contentHash, 0, combinedHash, 0, contentHash.Length);
                    Buffer.BlockCopy(propertiesHash, 0, combinedHash, contentHash.Length, propertiesHash.Length);

                    // 将哈希值转换为字符串表示
                    return BitConverter.ToString(sha256.ComputeHash(combinedHash)).Replace("-", "").ToLower();
                }
            }
        }
        // 分片大小为10MB
        public const int CHUNCK_SIZE = 10 * 1024 * 1024;
        public static void postFormForBigFile(string filePath)
        {
            using(System.IO.FileStream fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                byte[] buffer = new byte[CHUNCK_SIZE];
                int bytesRead;
                string fileName = System.IO.Path.GetFileName(filePath);
                string fileMd5 = GenerateFileMD5Identifier(filePath);
                int chunkIndex = 0;
                long totalSize = fileStream.Length;
                // 总片数
                int totalChunks = (int)Math.Ceiling((double)totalSize / CHUNCK_SIZE);

                // 先校验
                Dictionary<string, string> fileFormParam = new Dictionary<string, string>();
                fileFormParam.Add("md5", fileMd5);
                fileFormParam.Add("fileMd5", fileMd5);
                fileFormParam.Add("fileName", fileName);
                string idxStr = postFormData("http://localhost:8083/solar-verse/api/v1/common/file/check?organNo=100702002", fileFormParam);
                int idx = string.IsNullOrEmpty(idxStr) ? -1 : int.Parse(idxStr);
                if(idx == -1)
                {
                    return;
                }
                chunkIndex = idx;
                using (System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient())
                {
                   
                    while((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        System.Net.Http.MultipartFormDataContent content = new System.Net.Http.MultipartFormDataContent();
                        content.Add(new System.Net.Http.ByteArrayContent(buffer, 0, bytesRead), "file", fileName);
                        content.Add(new System.Net.Http.StringContent(fileName), "name");
                        content.Add(new System.Net.Http.StringContent(fileMd5), "md5");
                        content.Add(new System.Net.Http.StringContent(fileMd5), "uid");
                        content.Add(new System.Net.Http.StringContent(fileMd5 + "_" + chunkIndex.ToString()), "id");
                        content.Add(new System.Net.Http.StringContent(chunkIndex.ToString()), "chunk");
                        content.Add(new System.Net.Http.StringContent(totalChunks.ToString()), "chunks");
                        content.Add(new System.Net.Http.StringContent(totalSize.ToString()), "size");
                        System.Net.Http.HttpResponseMessage response = httpClient.PostAsync("http://localhost:8083/solar-verse/api/v1/common/file/upload?organNo=100702002", content).Result;
                        if (null == response)
                        {
                            throw new Exception("[NPE]HTTP请求异常");
                        }
                        if (response.IsSuccessStatusCode)
                        {
                            string result = response.Content.ReadAsStringAsync().Result;
                            var resultObj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(result);
                            int code = resultObj.code;
                            if (200 == code)
                            {
                                var data = resultObj.data;
                                Newtonsoft.Json.JsonConvert.SerializeObject(data);
                                chunkIndex++;
                            }
                            else
                            {
                                string message = resultObj.message;
                                message = "[" + code + "]" + message;
                                throw new Exception(message);
                            }
                        }
                        else
                        {
                            string message = "[" + response.StatusCode.ToString() + "]HTTP请求异常";
                            throw new Exception(message);
                        }

                    }

                    postFormData("http://localhost:8083/solar-verse/api/v1/common/file/merge?organNo=100702002", fileFormParam);
                }

            }
        }
        public static string postFormData(string url, Dictionary<string, string> formData) 
        {
            using (System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient())
            {
                using (System.Net.Http.FormUrlEncodedContent formContent = new System.Net.Http.FormUrlEncodedContent(formData))
                {
                    System.Net.Http.HttpResponseMessage response = httpClient.PostAsync(url, formContent).Result;
                    if (null == response)
                    {
                        throw new Exception("[NPE]HTTP请求异常");
                    }
                    if (response.IsSuccessStatusCode)
                    {
                        string result = response.Content.ReadAsStringAsync().Result;
                        var resultObj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(result);
                        int code = resultObj.code;
                        if (200 == code)
                        {
                            var data = resultObj.data;
                            return Newtonsoft.Json.JsonConvert.SerializeObject(data);
                        }
                        else
                        {
                            string message = resultObj.message;
                            message = "[" + code + "]" + message;
                            throw new Exception(message);
                        }
                    }
                    else
                    {
                        string message = "[" + response.StatusCode.ToString() + "]HTTP请求异常";
                        throw new Exception(message);
                    }
                }
            }
        }
    }
}
